/**
 * Copyright(c) 2014 Xunton Solutions
 *
 * History:
 *   15-1-10 下午4:21 Created by dwzhang
 */
package com.jade.modules.region.impl;

import java.util.List;
import javax.ejb.TransactionAttribute;
import javax.inject.Inject;
import javax.inject.Named;

import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.util.PagingList;
import com.jade.framework.base.util.PinyinUtils;
import com.jade.modules.region.Region;
import com.jade.modules.region.RegionDao;
import com.jade.modules.region.RegionException;
import com.jade.modules.region.RegionManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

/**
 * 地区管理实现。
 *
 * @author sky
 * @version 1.0 13-4-23 下午1:55
 */
@Named ("module_regionManager")
public class RegionManagerImpl
        implements RegionManager
{
    protected RegionDao regionDao;

    @Inject
    public void setRegionDao(@Named ("module_regionDao") RegionDao regionDao)
    {
        this.regionDao = regionDao;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public void addRegion(Region region)
            throws RegionException
    {
        setRegionSpell(region);
        if (regionDao.getRegion(region.getId()) != null) {
            throw new RegionException("err.module.region.existed_region", region.getId());
        }
        regionDao.addRegion(region);
    }

    protected void setRegionSpell(Region region)
    {
        String cnName = region.getCnName();
        if (StringUtils.isNotBlank(cnName)) {
            if (StringUtils.isBlank(region.getFirstSpell())) {
                String firstSpell = PinyinUtils.getFirstSpell(cnName);
                region.setFirstSpell(StringUtils.replace(firstSpell, "u:", "u"));
            }
            if (StringUtils.isBlank(region.getFullSpell())) {
                String fullSpell = PinyinUtils.getFullSpell(cnName);
                region.setFullSpell(StringUtils.replace(fullSpell, "u:", "u"));
            }
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public void updateRegion(Region region)
            throws RegionException
    {
        setRegionSpell(region);
        regionDao.updateRegion(region);
    }

    public Region getRegion(String id)
    {
        return regionDao.getRegion(id);
    }

    public Region getRegionByName(String name, String type)
    {
        Criteria criteria = new Criteria();
        criteria.add(Restrictions.or(Restrictions.eq("cnName", name), Restrictions.eq("abbrCnName", name),
                Restrictions.eq("enName", name)));
        criteria.add(Restrictions.eq("type", type));
        List<Region> regions = regionDao.listRegion(criteria);
        return regions.isEmpty() ? null : regions.get(0);
    }

    public Region getSubRegion(String parentId, String name)
    {
        Criteria criteria = new Criteria();
        if (StringUtils.isNotBlank(parentId)) {
            criteria.add(Restrictions.eq("parentId", parentId));
        }
        else {
            criteria.add(Restrictions.isNull("parentId"));
        }
        criteria.add(Restrictions.or(Restrictions.eq("cnName", name), Restrictions.eq("abbrCnName", name),
                Restrictions.eq("enName", name)));
        List<Region> regions = regionDao.listRegion(criteria);
        return regions.isEmpty() ? null : regions.get(0);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public void removeRegion(String... ids)
            throws RegionException
    {
        for (String id : ids) {
            Region region = getRegion(id);
            if (region != null) {
                if (hasChild(id)) {
                    throw new RegionException("err.module.region.remove_has_children", id);
                }
                regionDao.removeRegion(region);
            }
        }
    }

    protected boolean hasChild(String pid)
    {
        List<Region> regions = listRegion(pid);
        return !regions.isEmpty();
    }

    public List<Region> listRegion(String parentId)
    {
        Criteria criteria = new Criteria();
        if (StringUtils.isBlank(parentId)) {
            criteria.add(Restrictions.isNull("parentId"));
        }
        else {
            criteria.add(Restrictions.eq("parentId", parentId));
        }
        return listRegion(criteria);
    }

    public List<Region> listRegion(String parentId, int level)
    {
        List<Region> regions = listRegion(parentId);
        if (level > 1) {
            for (Region region : regions) {
                region.setChildren(listRegion(region.getId(), level - 1));
            }
        }
        return regions;
    }

    public List<Region> listRegion(Criteria criteria)
    {
        return regionDao.listRegion(criteria);
    }

    public PagingList<Region> queryRegion(Criteria criteria)
    {
        return regionDao.queryRegion(criteria);
    }
}